package com.google.code.coma.gui.space;

import com.google.code.coma.domain.Computer;
import com.google.code.coma.domain.Part;
import com.google.code.coma.gui.DataProvider;
import com.google.code.coma.space.SelectAllSelectorCallback;
import com.google.code.coma.space.SpaceSelector;
import com.google.code.coma.space.util.SpaceManager;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.ListView;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.mozartspaces.core.*;
import org.mozartspaces.notifications.Notification;
import org.mozartspaces.notifications.NotificationListener;
import org.mozartspaces.notifications.NotificationManager;
import org.mozartspaces.notifications.Operation;

import java.io.Serializable;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Dominik Strasser, dominikstr@gmail.com
 */
public class SpaceComputerDataProvider implements DataProvider<Computer> {
	private MzsCore core;

	private Capi capi;

	private ContainerReference containerReference;

	private ObservableList<Computer> data = FXCollections.observableArrayList();

	private static final Log log = LogFactory.getLog(SpaceComputerDataProvider.class);

	public SpaceComputerDataProvider(String spaceURI, String container) {
		core = DefaultMzsCore.newInstance(0);
		capi = new Capi(core);
		try {
			containerReference = SpaceManager.getOrCreateNamedContainer(URI.create(spaceURI), container, capi);
		} catch (MzsCoreException e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public void bind(final ListView<Computer> computerListView) {
		computerListView.setItems(data);
		try {
			data.addAll(capi.read(containerReference, new SpaceSelector(new SelectAllSelectorCallback()), 1000, null).toArray(new Computer[]{}));
		} catch (MzsCoreException e) {
			//nothing to do here
		}
		NotificationManager notifManager = new NotificationManager(core);
		try {
			notifManager.createNotification(containerReference, new NotificationListener() {

				@Override
				public void entryOperationFinished(Notification source, Operation operation, final List<? extends Serializable> entries) {
					final List<Computer> newData;
					try {
						newData = capi.read(containerReference, new SpaceSelector(new SelectAllSelectorCallback()), 1000, null);
					} catch (MzsCoreException e) {
						log.info("Unable to update list.");
						return;
					}
					Platform.runLater(new Runnable() {
						@Override
						public void run() {
							data.clear();
							data.addAll(newData);
						}
					});
				}
			}, Operation.WRITE, Operation.TAKE, Operation.DELETE);
		} catch (Exception e) {
			log.error("Unable to create notification", e);
		}
	}

	@Override
	public void shutdown() {

	}
}
